package net.simflow.swf.analyzer.chart;

import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.TreeSet;

import net.simflow.swf.analyzer.data.StringConstant;
import net.simflow.swf.analyzer.data.TupleStrInt;
import net.simflow.swf.analyzer.graph.stats.data.GraphStats;
import net.simflow.swf.analyzer.network.data.Link;
import net.simflow.swf.analyzer.network.data.Node;

public class GraphStatsChart {
	private static final int MAX_LENGTH = 10;

	private static GraphStatsChart instance = new GraphStatsChart();

	private GraphStatsChart() {
	}

	public static GraphStatsChart getInstance() {
		return instance;
	}

	public ArrayList<TupleStrInt> generate(String style, GraphStats gstats) {
		switch (style) {
		case GraphStats.GRAPH_NAME:
			return this.getNameString(gstats);
		case GraphStats.VERTEX_NUMBER:
			return this.getVertexCountString(gstats);
		case GraphStats.EDGE_NUMBER:
			return this.getEdgeCountString(gstats);
		case GraphStats.VERTICES:
			return this.getVertexNameListString(gstats);
		case GraphStats.EDGES:
			return this.getEdgeNameListString(gstats);
		case GraphStats.DEGREE_DISTRIBUTION:
			return this.getDegreeDistributionString(gstats);
		}
		return null;
	}

	private ArrayList<TupleStrInt> getNameString(GraphStats gstats) {
		if (gstats.getGraphName() == null) {
			return null;
		}

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		info.add(new TupleStrInt(GraphStats.GRAPH_NAME, StringConstant.TITLE));
		info.add(new TupleStrInt(gstats.getGraphName(), StringConstant.CONTENT));
		return info;
	}

	private ArrayList<TupleStrInt> getVertexCountString(GraphStats gstats) {
		int c = gstats.getNodeCount();
		if (c == -1) {
			return null;
		}

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		info.add(new TupleStrInt(GraphStats.VERTEX_NUMBER, StringConstant.TITLE));
		info.add(new TupleStrInt(String.valueOf(c), StringConstant.CONTENT));
		return info;
	}

	private ArrayList<TupleStrInt> getEdgeCountString(GraphStats gstats) {
		int c = gstats.getLinkCount();
		if (c == -1) {
			return null;
		}

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		info.add(new TupleStrInt(GraphStats.EDGE_NUMBER, StringConstant.TITLE));
		info.add(new TupleStrInt(String.valueOf(c), StringConstant.CONTENT));
		return info;
	}

	private ArrayList<TupleStrInt> getVertexNameListString(GraphStats gstats) {
		if (gstats.getNodeArray() == null) {
			return null;
		}

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();

		for (Node node : gstats.getNodeArray()) {
			info.add(new TupleStrInt(node.getNameInNetwork(),
					StringConstant.CONTENT));
		}

		if (info.isEmpty()) {
			return null;
		}

		info.add(0, new TupleStrInt(GraphStats.VERTICES, StringConstant.TITLE));
		return info;
	}

	private ArrayList<TupleStrInt> getEdgeNameListString(GraphStats gstats) {
		if (gstats.getLinkArray() == null) {
			return null;
		}

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		for (Link link : gstats.getLinkArray()) {
			info.add(new TupleStrInt(link.getShortInfo(),
					StringConstant.CONTENT));
		}

		if (info.isEmpty()) {
			return null;
		}

		info.add(0, new TupleStrInt(GraphStats.EDGES, StringConstant.TITLE));
		return info;
	}

	private ArrayList<TupleStrInt> getDegreeDistributionString(GraphStats gstats) {
		if (gstats.getDegreeDistribution() == null) {
			return null;
		}
		gstats.getDegreeDistribution().comparator();

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		for (Entry<Integer, ArrayList<Node>> en : gstats
				.getDegreeDistribution().descendingMap().entrySet()) {
			TreeSet<String> set = new TreeSet<String>();
			for (Node node : en.getValue()) {
				set.add(node.getNameInNetwork());
				if (set.size() >= MAX_LENGTH) {
					break;
				}
			}
			set.comparator();

			StringBuffer str = new StringBuffer();
			str.append(en.getKey());
			str.append(" (").append(en.getValue().size()).append("): ");
			for (String s : set) {
				str.append(" ").append(s).append(";");
			}
			if (set.size() >= MAX_LENGTH && en.getValue().size() > MAX_LENGTH) {
				str.append("...");
			}

			info.add(new TupleStrInt(str.toString(), StringConstant.CONTENT));
		}

		if (info.isEmpty()) {
			return null;
		}

		info.add(0, new TupleStrInt(GraphStats.DEGREE_DISTRIBUTION,
				StringConstant.TITLE));
		return info;
	}
}
